package com.github.beihaifeiwu.myspring.http.feign;

import com.github.beihaifeiwu.myspring.core.SpringBeans;
import feign.Client;
import feign.Contract;
import feign.Feign;
import feign.Logger;
import feign.Request;
import feign.RequestInterceptor;
import feign.Retryer;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * Created by liupin on 2017/9/6.
 */
public class FeignBuilderFactoryBean implements FactoryBean<Feign.Builder>, InitializingBean {

    public static final String BEAN_NAME = "feignBuilderFactoryBean";

    private Logger logger;
    private Request.Options options;

    private final FeignProperties properties;
    private final List<RequestInterceptor> interceptors;
    private final List<FeignBuilderConfigurer> configurers;

    public FeignBuilderFactoryBean(FeignProperties properties,
                                   List<RequestInterceptor> interceptors,
                                   List<FeignBuilderConfigurer> configurers) {
        this.properties = properties;
        this.interceptors = interceptors;
        this.configurers = configurers;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        logger = new FeignSlf4jLogger(properties.getLogging().getLogName(), properties.getLogging().getLogLevel());
        options = new Request.Options(properties.getConnectTimeoutMillis(), properties.getReadTimeoutMillis());
    }

    @Nullable
    @Override
    public Feign.Builder getObject() throws Exception {
        Feign.Builder builder = Feign.builder();

        builder.logger(logger);
        builder.logLevel(Logger.Level.valueOf(properties.getLogging().getLevel().name()));
        builder.options(options);

        SpringBeans.getBean(Client.class).ifPresent(builder::client);
        SpringBeans.getBean(Contract.class).ifPresent(builder::contract);
        SpringBeans.getBean(Retryer.class).ifPresent(builder::retryer);
        SpringBeans.getBean(Decoder.class).ifPresent(builder::decoder);
        SpringBeans.getBean(Encoder.class).ifPresent(builder::encoder);
        SpringBeans.getBean(ErrorDecoder.class).ifPresent(builder::errorDecoder);

        if (!CollectionUtils.isEmpty(interceptors)) {
            interceptors.forEach(builder::requestInterceptor);
        }

        if (!CollectionUtils.isEmpty(configurers)) {
            for (FeignBuilderConfigurer configurer : configurers) {
                configurer.configure(builder);
            }
        }

        return builder;
    }

    @Nullable
    @Override
    public Class<?> getObjectType() {
        return Feign.Builder.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

}
